<?php
namespace app\service;

use think\facade\Db;

class LeaveApprovalService
{
    /**
     * 处理审批通过的记录，检查是否为请假类型并生成打卡记录
     */
    public function handleApprovalPassed($approvalRecord)
    {
        // 写入详细日志
        //$this->writeLog('=== 开始处理请假审批通过 ===');
        //$this->writeLog('审批记录: ' . json_encode($approvalRecord, JSON_UNESCAPED_UNICODE));
        
        try {
            // 1. 检查是否为请假类型的审批
            //$this->writeLog('步骤1: 检查是否为请假类型审批, flow_id=' . $approvalRecord['flow_id']);
            
            $flow = Db::name('approval_flow')
                ->where('id', $approvalRecord['flow_id'])
                ->where('is_leave_type', 1)
                ->where('status', 1)
                ->find();
            
            //$this->writeLog('查询审批流程结果: ' . json_encode($flow, JSON_UNESCAPED_UNICODE));
            
            if (!$flow) {
                //$this->writeLog('不是请假类型或流程已停用，跳过处理');
                return false;
            }
            
            // 2. 解析表单数据，提取请假时间信息
            //$this->writeLog('步骤2: 解析表单数据');
            //$this->writeLog('原始表单数据: ' . $approvalRecord['form_data']);
            
            $leaveInfo = $this->parseLeaveFormData($approvalRecord['form_data']);
            //$this->writeLog('解析后的请假信息: ' . json_encode($leaveInfo, JSON_UNESCAPED_UNICODE));
            
            if (!$leaveInfo) {
                //$this->writeLog('无法解析请假信息，处理失败');
                return false;
            }
            
            // 3. 获取用户的考勤设置
            //$this->writeLog('步骤3: 获取考勤设置, user_id=' . $approvalRecord['user_id']);
            
            $attendanceSetting = $this->getAttendanceSetting($approvalRecord['user_id']);
            //$this->writeLog('考勤设置: ' . json_encode($attendanceSetting, JSON_UNESCAPED_UNICODE));
            
            if (!$attendanceSetting) {
                //$this->writeLog('无法获取用户考勤设置，处理失败');
                return false;
            }
            
            // 4. 生成请假期间的打卡记录
            //$this->writeLog('步骤4: 开始生成请假打卡记录');
            $this->generateLeaveAttendanceRecords($approvalRecord['user_id'], $leaveInfo, $attendanceSetting);
            
            //$this->writeLog('请假打卡记录生成完成');
            //$this->writeLog('=== 处理请假审批通过结束 ===');
            return true;
            
        } catch (\Exception $e) {
            //$this->writeLog('处理异常: ' . $e->getMessage());
            //$this->writeLog('异常堆栈: ' . $e->getTraceAsString());
            return false;
        }
    }
    
    /**
     * 解析请假表单数据，提取时间信息
     */
    private function parseLeaveFormData($formDataJson)
    {
        $formData = json_decode($formDataJson, true);
        if (!$formData || !is_array($formData)) {
            return null;
        }
        
        $leaveInfo = [
            'start_time' => '',
            'end_time' => '',
            'reason' => ''
        ];
        
        // 根据flowId=26的字段结构解析
        // field_s9w6q4k60: 开始时间
        // field_88qqnb9wf: 结束时间  
        // field_12jq31m9z: 备注
        
        if (isset($formData['field_s9w6q4k60'])) {
            $leaveInfo['start_time'] = $this->formatDateTime($formData['field_s9w6q4k60']);
        }
        
        if (isset($formData['field_88qqnb9wf'])) {
            $leaveInfo['end_time'] = $this->formatDateTime($formData['field_88qqnb9wf']);
        }
        
        if (isset($formData['field_12jq31m9z'])) {
            $leaveInfo['reason'] = $formData['field_12jq31m9z'];
        }
        
        // 验证必要字段
        if (empty($leaveInfo['start_time']) || empty($leaveInfo['end_time'])) {
            return null;
        }
        
        return $leaveInfo;
    }
    
    /**
     * 格式化日期时间
     */
    private function formatDateTime($dateTimeString)
    {
        // 处理ISO格式时间：2025-07-13T15:30:49.000Z
        $timestamp = strtotime($dateTimeString);
        if ($timestamp === false) {
            return '';
        }
        
        return date('Y-m-d H:i:s', $timestamp);
    }
    
    /**
     * 获取用户考勤设置
     */
    private function getAttendanceSetting($userId)
    {
        // 获取考勤打卡设置
        $setting = Db::name('checkin_setting')
            ->where('status', 1)
            ->order('id desc')
            ->find();
            
        if (!$setting) {
            // 默认设置：两次上下班
            return [
                'work_type' => 2,
                'morning_start_time' => '08:00:00',
                'morning_end_time' => '12:00:00', 
                'afternoon_start_time' => '14:00:00',
                'afternoon_end_time' => '18:00:00'
            ];
        }
        
        // 转换字段名以匹配代码逻辑
        return [
            'work_type' => $setting['work_type'],
            'morning_start_time' => $setting['morning_start_time'],
            'morning_end_time' => $setting['morning_end_time'],
            'afternoon_start_time' => $setting['afternoon_start_time'],
            'afternoon_end_time' => $setting['afternoon_end_time']
        ];
    }
    
    /**
     * 生成请假期间的打卡记录
     */
    private function generateLeaveAttendanceRecords($userId, $leaveInfo, $attendanceSetting)
    {
        //$this->writeLog('开始生成请假打卡记录');
        
        $startTime = strtotime($leaveInfo['start_time']);
        $endTime = strtotime($leaveInfo['end_time']);
        
        //$this->writeLog('请假时间戳: 开始=' . $startTime . ', 结束=' . $endTime);
        
        // 按天遍历请假时间段
        $currentDate = date('Y-m-d', $startTime);
        $endDate = date('Y-m-d', $endTime);
        
        //$this->writeLog('请假日期范围: ' . $currentDate . ' 到 ' . $endDate);
        
        $current = strtotime($currentDate);
        $end = strtotime($endDate);
        
        while ($current <= $end) {
            $dateStr = date('Y-m-d', $current);
            //$this->writeLog('处理日期: ' . $dateStr);
            
            // 计算当天请假涉及的打卡时间段
            $punchTimes = $this->calculatePunchTimesForDate($dateStr, $leaveInfo, $attendanceSetting);
            //$this->writeLog('计算出的打卡时间段: ' . json_encode($punchTimes, JSON_UNESCAPED_UNICODE));
            
            // 如果当天有请假涉及的打卡时间，则创建或更新记录
            if (!empty($punchTimes)) {
                //$this->writeLog('开始创建或更新' . $dateStr . '的打卡记录');
                $this->createOrUpdateLeaveRecord($userId, $dateStr, $punchTimes, $attendanceSetting);
            } else {
                //$this->writeLog('日期' . $dateStr . '无需生成打卡记录');
            }
            
            $current = strtotime('+1 day', $current);
        }
        
        //$this->writeLog('请假打卡记录生成完毕');
    }
    
    /**
     * 创建或更新请假打卡记录
     */
    private function createOrUpdateLeaveRecord($userId, $date, $punchTimes, $attendanceSetting)
    {
        //$this->writeLog('开始创建或更新打卡记录: 用户ID=' . $userId . ', 日期=' . $date);
        
        // 检查当天是否已有打卡记录
        $existingRecord = Db::name('attendance_record')
            ->where('user_id', $userId)
            ->where('check_date', $date)
            ->find();
            
        //$this->writeLog('查询现有记录结果: ' . json_encode($existingRecord, JSON_UNESCAPED_UNICODE));
            
        if ($existingRecord) {
            // 更新现有记录的请假状态
            $updateData = ['update_time' => date('Y-m-d H:i:s')];
            
            foreach ($punchTimes as $punchTime) {
                switch ($punchTime['type']) {
                    case 1:
                        $updateData['morning_check_in_status'] = 4; // 请假状态
                        break;
                    case 2:
                        $updateData['morning_check_out_status'] = 4;
                        break;
                    case 3:
                        $updateData['afternoon_check_in_status'] = 4;
                        break;
                    case 4:
                        $updateData['afternoon_check_out_status'] = 4;
                        break;
                }
            }
            
            //$this->writeLog('准备更新数据: ' . json_encode($updateData, JSON_UNESCAPED_UNICODE));
            
            try {
                $result = Db::name('attendance_record')
                    ->where('id', $existingRecord['id'])
                    ->update($updateData);
                    
                //$this->writeLog('更新结果: ' . ($result ? '成功' : '失败'));
            } catch (\Exception $e) {
                //$this->writeLog('更新异常: ' . $e->getMessage());
            }
        } else {
            // 创建新的打卡记录
            $data = [
                'user_id' => $userId,
                'check_date' => $date,
                'work_type' => $attendanceSetting['work_type'],
                'status' => 1, // 正常状态
                'abnormal_reason' => null,
                'remark' => '系统自动生成（请假审批通过）',
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s'),
                // 初始化 除请假外 其他状态为缺卡
                'morning_check_in_status' => 3,
                'morning_check_out_status' => 3,
                'afternoon_check_in_status' => 3,
                'afternoon_check_out_status' => 3
            ];
            
            // 根据请假涉及的打卡时间设置对应状态
            foreach ($punchTimes as $punchTime) {
                switch ($punchTime['type']) {
                    case 1:
                        $data['morning_check_in_status'] = 4; // 请假状态
                        break;
                    case 2:
                        $data['morning_check_out_status'] = 4;
                        break;
                    case 3:
                        $data['afternoon_check_in_status'] = 4;
                        break;
                    case 4:
                        $data['afternoon_check_out_status'] = 4;
                        break;
                }
            }
            
            //$this->writeLog('准备插入新记录: ' . json_encode($data, JSON_UNESCAPED_UNICODE));
            
            try {
                $result = Db::name('attendance_record')->insert($data);
                //$this->writeLog('插入结果: ' . ($result ? '成功' : '失败'));
            } catch (\Exception $e) {
                //$this->writeLog('插入异常: ' . $e->getMessage());
            }
        }
    }
    
    /**
     * 计算指定日期的请假打卡时间段
     */
    private function calculatePunchTimesForDate($date, $leaveInfo, $attendanceSetting)
    {
        //$this->writeLog('计算日期' . $date . '的打卡时间段');
        
        $punchTimes = [];
        $dateStart = strtotime($date . ' 00:00:00');
        $dateEnd = strtotime($date . ' 23:59:59');
        $leaveStart = strtotime($leaveInfo['start_time']);
        $leaveEnd = strtotime($leaveInfo['end_time']);
        
        //$this->writeLog('时间戳对比: 日期开始=' . $dateStart . ', 日期结束=' . $dateEnd . ', 请假开始=' . $leaveStart . ', 请假结束=' . $leaveEnd);
        
        // 如果请假时间与当天有交集
        if ($leaveStart <= $dateEnd && $leaveEnd >= $dateStart) {
            //$this->writeLog('请假时间与当天有交集，开始计算打卡时间段');
            
            // 根据work_type确定打卡次数
            if ($attendanceSetting['work_type'] == 1) {
                //$this->writeLog('一次上下班模式');
                // 一次上下班模式：2次打卡
                $morningStart = strtotime($date . ' ' . $attendanceSetting['morning_start_time']);
                $morningEnd = strtotime($date . ' ' . $attendanceSetting['morning_end_time']);
                
                //$this->writeLog('上班时间=' . $morningStart . ', 下班时间=' . $morningEnd);
                
                // 检查上班时间是否在请假范围内
                if ($leaveStart <= $morningStart && $leaveEnd >= $morningStart) {
                    $punchTimes[] = ['type' => 1, 'time' => null]; // 上班打卡
                    //$this->writeLog('添加上班打卡');
                }
                
                // 检查下班时间是否在请假范围内  
                if ($leaveStart <= $morningEnd && $leaveEnd >= $morningEnd) {
                    $punchTimes[] = ['type' => 2, 'time' => null]; // 下班打卡
                    //$this->writeLog('添加下班打卡');
                }
                
            } else {
                //$this->writeLog('两次上下班模式');
                // 两次上下班模式：4次打卡
                $morningStart = strtotime($date . ' ' . $attendanceSetting['morning_start_time']);
                $morningEnd = strtotime($date . ' ' . $attendanceSetting['morning_end_time']);
                $afternoonStart = strtotime($date . ' ' . $attendanceSetting['afternoon_start_time']);
                $afternoonEnd = strtotime($date . ' ' . $attendanceSetting['afternoon_end_time']);
                
                //$this->writeLog('上午上班=' . $morningStart . ', 上午下班=' . $morningEnd . ', 下午上班=' . $afternoonStart . ', 下午下班=' . $afternoonEnd);
                
                // 检查各个打卡时间是否在请假范围内
                if ($leaveStart <= $morningStart && $leaveEnd >= $morningStart) {
                    $punchTimes[] = ['type' => 1, 'time' => null]; // 上午上班
                    //$this->writeLog('添加上午上班打卡');
                }
                if ($leaveStart <= $morningEnd && $leaveEnd >= $morningEnd) {
                    $punchTimes[] = ['type' => 2, 'time' => null]; // 上午下班
                    //$this->writeLog('添加上午下班打卡');
                }
                if ($leaveStart <= $afternoonStart && $leaveEnd >= $afternoonStart) {
                    $punchTimes[] = ['type' => 3, 'time' => null]; // 下午上班
                    //$this->writeLog('添加下午上班打卡');
                }
                if ($leaveStart <= $afternoonEnd && $leaveEnd >= $afternoonEnd) {
                    $punchTimes[] = ['type' => 4, 'time' => null]; // 下午下班
                    //$this->writeLog('添加下午下班打卡');
                }
            }
        } else {
            //$this->writeLog('请假时间与当天无交集');
        }
        
        //$this->writeLog('最终计算结果: ' . json_encode($punchTimes, JSON_UNESCAPED_UNICODE));
        return $punchTimes;
    }
    
    
    /**
     * 更新请假期间的考勤记录状态
     */
    private function updateAttendanceForLeave($leaveInfo)
    {
        $startDate = $leaveInfo['start_date'];
        $endDate = $leaveInfo['end_date'];
        $userId = $leaveInfo['user_id'] ?? 0;
        
        if (!$userId) {
            return;
        }
        
        // 查询请假期间的考勤记录
        $records = Db::name('attendance_record')
            ->where('user_id', $userId)
            ->where('check_date', 'between', [$startDate, $endDate])
            ->select();
        
        // 更新状态为请假
        foreach ($records as $record) {
            Db::name('attendance_record')
                ->where('id', $record['id'])
                ->update([
                    'status' => 4, // 请假状态
                    'abnormal_reason' => '请假',
                    'update_time' => date('Y-m-d H:i:s')
                ]);
        }
        
        // 为没有考勤记录的请假日期创建记录
        $current = strtotime($startDate);
        $end = strtotime($endDate);
        
        while ($current <= $end) {
            $currentDate = date('Y-m-d', $current);
            
            // 检查是否已有记录
            $exists = Db::name('attendance_record')
                ->where('user_id', $userId)
                ->where('check_date', $currentDate)
                ->find();
            
            if (!$exists) {
                // 创建请假记录
                Db::name('attendance_record')->insert([
                    'user_id' => $userId,
                    'check_date' => $currentDate,
                    'status' => 4, // 请假
                    'abnormal_reason' => '请假',
                    'remark' => '系统自动生成（请假）',
                    'create_time' => date('Y-m-d H:i:s')
                ]);
            }
            
            $current = strtotime('+1 day', $current);
        }
    }
    
    /**
     * 写入日志到文件
     */
    private function writeLog($message)
    {
        $logFile = __DIR__ . '/leave_approval_' . date('Y-m-d') . '.log';
        
        $timestamp = date('Y-m-d H:i:s');
        $logMessage = "[{$timestamp}] {$message}" . PHP_EOL;
        
        file_put_contents($logFile, $logMessage, FILE_APPEND | LOCK_EX);
    }
}